package com.youlu.campus.admin.tencentcloud.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.tencentcloudapi.clb.v20180317.ClbClient;
import com.tencentcloudapi.clb.v20180317.models.Backend;
import com.tencentcloudapi.clb.v20180317.models.CreateRuleRequest;
import com.tencentcloudapi.clb.v20180317.models.CreateRuleResponse;
import com.tencentcloudapi.clb.v20180317.models.DescribeLoadBalancersRequest;
import com.tencentcloudapi.clb.v20180317.models.DescribeLoadBalancersResponse;
import com.tencentcloudapi.clb.v20180317.models.DescribeTargetsRequest;
import com.tencentcloudapi.clb.v20180317.models.DescribeTargetsResponse;
import com.tencentcloudapi.clb.v20180317.models.HealthCheck;
import com.tencentcloudapi.clb.v20180317.models.ListenerBackend;
import com.tencentcloudapi.clb.v20180317.models.LoadBalancer;
import com.tencentcloudapi.clb.v20180317.models.RegisterTargetsRequest;
import com.tencentcloudapi.clb.v20180317.models.RegisterTargetsResponse;
import com.tencentcloudapi.clb.v20180317.models.RuleInput;
import com.tencentcloudapi.clb.v20180317.models.RuleTargets;
import com.tencentcloudapi.clb.v20180317.models.Target;
import com.tencentcloudapi.common.exception.TencentCloudSDKException;
import com.tencentcloudapi.cvm.v20170312.CvmClient;
import com.tencentcloudapi.cvm.v20170312.models.DescribeInstancesRequest;
import com.tencentcloudapi.cvm.v20170312.models.DescribeInstancesResponse;
import com.tencentcloudapi.cvm.v20170312.models.Filter;
import com.tencentcloudapi.cvm.v20170312.models.Instance;
import com.tencentcloudapi.dnspod.v20210323.DnspodClient;
import com.tencentcloudapi.dnspod.v20210323.models.CreateRecordRequest;
import com.tencentcloudapi.dnspod.v20210323.models.CreateRecordResponse;
import com.tencentcloudapi.dnspod.v20210323.models.DescribeDomainListRequest;
import com.tencentcloudapi.dnspod.v20210323.models.DescribeDomainListResponse;
import com.tencentcloudapi.dnspod.v20210323.models.DescribeRecordListRequest;
import com.tencentcloudapi.dnspod.v20210323.models.DescribeRecordListResponse;
import com.tencentcloudapi.dnspod.v20210323.models.DomainListItem;
import com.tencentcloudapi.dnspod.v20210323.models.RecordListItem;
import com.youlu.campus.admin.tencentcloud.entity.DomainRecordRequest;
import com.youlu.campus.admin.tencentcloud.entity.TencentCloudCLBIdInfo;
import com.youlu.campus.admin.tencentcloud.entity.TencentCloudConfig;
import com.youlu.campus.admin.tencentcloud.entity.TencentDnsRecord;
import com.youlu.campus.admin.tencentcloud.entity.TencentDomainItem;
import com.youlu.campus.admin.tencentcloud.service.TencentCloudConfigService;
import com.youlu.campus.admin.tencentcloud.service.TencentCloudService;
import com.youlu.campus.admin.tencentcloud.service.TencentDnsRecordService;
import com.youlu.campus.admin.tencentcloud.service.TencentDomainItemService;
import com.youlu.campus.admin.tencentcloud.utils.TencentCloudClientUtil;
import com.youlu.campus.common.exception.BusinessException;
import com.youlu.campus.common.utils.RedisKeyUtil;
import com.yuelin.infrastructure.quantum.common.QResult;
import io.jsonwebtoken.lang.Collections;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 腾讯云 操作
 *
 * @Description: TencentServiceImpl
 * @Date 2025/8/19
 * @module TencentServiceImpl
 * @author: su
 */
@Slf4j
@Service
public class TencentCloudServiceImpl implements TencentCloudService {

    private static final String DOMAIN_PREFIX = "https://";


    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @Autowired
    private TencentCloudConfigService tencentCloudConfigService;

    @Autowired
    private TencentDomainItemService tencentDomainItemService;

    @Autowired
    private TencentDnsRecordService tencentDnsRecordService;


    @Override
    public void initTencentCloudData() {
        log.info("initTencentCloudData start");
        List<TencentCloudConfig> dnsConfigs = tencentCloudConfigService.findByType(TencentCloudConfig.DNS);
        if (CollectionUtils.isEmpty(dnsConfigs)) {
            log.error("initTencentCloudData 未找到腾讯云DNS配置");
            return;
        }
        LoadBalancer[] loadBalancers = getLoadBalancers();
        List<String> loadBalancerNameList = Arrays.stream(loadBalancers).map(LoadBalancer::getLoadBalancerName).collect(Collectors.toList());
        List<TencentDomainItem> arrayList = new ArrayList();
        for (TencentCloudConfig config : dnsConfigs) {
            //创建连接
            DnspodClient client = TencentCloudClientUtil.createDnsClient(config);
            // 构造请求参数
            DescribeDomainListRequest req = new DescribeDomainListRequest();
            req.setType("ALL");
            req.setLimit(3000L); // 设置较大限制以获取更多域名
            DescribeDomainListResponse resp;
            try {
                // 发送请求并返回结果
                resp = client.DescribeDomainList(req);
            } catch (Exception e) {
                log.error("findDomainList 查询全部域名失败error", e);
                throw new BusinessException("DNS调用异常:查询全部域名失败");
            }
            DomainListItem[] domainList = resp.getDomainList();
            log.info("findDomainList 获取全部域名结果 domainList:{}", JSONObject.toJSONString(domainList));
            if (ArrayUtils.isEmpty(resp.getDomainList())) {
                continue;
            }
            for (DomainListItem domainListItem : resp.getDomainList()) {
                for (String loadBalancerName : loadBalancerNameList) {
                    if (loadBalancerName.contains(domainListItem.getName())) {
                        TencentDomainItem domainItemVo = new TencentDomainItem();
                        domainItemVo.setStatus(domainListItem.getStatus());
                        domainItemVo.setConfigId(config.getId());
                        domainItemVo.setDomain(domainListItem.getName());
                        domainItemVo.setDomainId(domainListItem.getDomainId());
                        arrayList.add(domainItemVo);
                        break;
                    }

                }
            }
        }
        log.info("initTencentCloudData  arrayList:{}", JSONObject.toJSONString(arrayList));
        //删除老数据
        tencentDomainItemService.deleteAll();
        tencentDnsRecordService.deleteAll();
        //存入新数据
        if (CollectionUtils.isNotEmpty(arrayList)) {
            tencentDomainItemService.insertAll(arrayList);
            for (TencentDomainItem tencentDomainItem : arrayList) {
                initTencentCloudRecordData(tencentDomainItem);
            }
        }

    }


    public void initTencentCloudRecordData(TencentDomainItem domainItem) {
        log.info("initTencentCloudRecordData start");
        TencentCloudConfig config = tencentCloudConfigService.findById(domainItem.getConfigId());
        if (config == null) {
            log.error("initTencentCloudRecordData 未找到腾讯云DNS配置");
            return;
        }
        String domain = domainItem.getDomain();
        //获取负载均衡绑定域名列表
        List<String> ruleTargetNames = getRuleTargetNames(domain);
        if (CollectionUtils.isEmpty(ruleTargetNames)) {
            return;
        }
        DescribeRecordListRequest req = new DescribeRecordListRequest();
        req.setDomain(domain);
        //获取连接
        DnspodClient client = TencentCloudClientUtil.createDnsClient(config);
        DescribeRecordListResponse resp = null;
        try {
            resp = client.DescribeRecordList(req);
        } catch (TencentCloudSDKException e) {
            log.error("initTencentCloudRecordData 获取DNS解析记录失败", e);
            throw new BusinessException("DNS调用异常:获取DNS解析记录失败");
        }
        if (ArrayUtils.isEmpty(resp.getRecordList())) {
            return;
        }
        List<TencentDnsRecord> arrayList = new ArrayList();
        for (RecordListItem recordListItem : resp.getRecordList()) {
            String domainName = recordListItem.getName() + "." + domain;
            if (ruleTargetNames.contains(domainName)) {
                TencentDnsRecord dnsRecordVo = new TencentDnsRecord();
                dnsRecordVo.setConfigId(domainItem.getConfigId());
                dnsRecordVo.setRecordId(recordListItem.getRecordId());
                dnsRecordVo.setRecordName(recordListItem.getName());
                dnsRecordVo.setStatus(recordListItem.getStatus());
                dnsRecordVo.setValue(recordListItem.getValue());
                dnsRecordVo.setDomain(domain);
                dnsRecordVo.setDomainName("https://" + domainName);
                arrayList.add(dnsRecordVo);
            }
        }
        if (CollectionUtils.isNotEmpty(arrayList)) {
            tencentDnsRecordService.insertAll(arrayList);
        }
    }

    private List<String> getRuleTargetNames(String domain) {
        List<TencentCloudConfig> configList = tencentCloudConfigService.findByType(TencentCloudConfig.CLB);
        if (Collections.isEmpty(configList)) {
            log.error("getRuleTargetNames 未找到腾讯云CLB配置");
            throw new BusinessException("未找到腾讯云CLB配置");
        }
        TencentCloudConfig clbConfig = configList.get(0);
        ClbClient clbClient = TencentCloudClientUtil.createClbClient(clbConfig);
        //获取负载均衡列表
        LoadBalancer loadBalancer = getLoadBalancersByDomain(clbClient, domain);
        DescribeTargetsRequest dreq = new DescribeTargetsRequest();
        dreq.setLoadBalancerId(loadBalancer.getLoadBalancerId());
        dreq.setPort(443L);
        // 调用接口
        DescribeTargetsResponse clbResp = null;
        try {
            clbResp = clbClient.DescribeTargets(dreq);
        } catch (TencentCloudSDKException e) {
            log.error("getRuleTargetNames 获取负载均衡失败", e);
            throw new BusinessException("DNS调用异常:获取负载均衡失败");
        }
        ListenerBackend[] listeners = clbResp.getListeners();
        log.info("getRuleTargetNames 验证是否重复  listeners:{}", JSONObject.toJSONString(listeners));
        if (ArrayUtils.isEmpty(listeners)) {
            return Arrays.asList();
        }
        //获取监听器id
        ListenerBackend listener = listeners[0];

        RuleTargets[] rules = listener.getRules();
        if (ArrayUtils.isEmpty(listeners)) {
            return Arrays.asList();
        }
        return Arrays.stream(rules).map(RuleTargets::getDomain).collect(Collectors.toList());
    }

    @Override
    public QResult createDomainRecord(DomainRecordRequest request) {
        log.info("createDomainRecord request:{}", JSON.toJSONString(request));
        String key = RedisKeyUtil.getDomainRecordAddKey();
        Boolean b = redisTemplate.opsForValue().setIfAbsent(key, "1", 10, TimeUnit.SECONDS);
        if (!b) {
            return QResult.fail("请勿频繁生成域名记录,请10秒后再试");
        }
        String configId = request.getConfigId();//主域名
        long domainId = request.getDomainId();//主域名
        String domain = request.getDomain();//主域名
        String suf = "." + domain;//域名后缀
        String subDomain = request.getSubDomain();//子域名 记录名称
        if (StringUtils.isBlank(subDomain)) {
            subDomain = getSubDomain(request);//年月日时
        }
        if (subDomain.endsWith(suf)) {
            subDomain = subDomain.substring(0, subDomain.length() - suf.length());
        }
        if (subDomain.startsWith(DOMAIN_PREFIX)) {
            subDomain = subDomain.substring(DOMAIN_PREFIX.length(), subDomain.length());
        }
        String successSubDomain = subDomain + suf;//成功的域名
        //1. 创建负载均衡
        //获取负载均衡配置 目前 clb 只有一个配置
        List<TencentCloudConfig> configList = tencentCloudConfigService.findByType(TencentCloudConfig.CLB);
        if (Collections.isEmpty(configList)) {
            log.error("getTencentCloudRepeatCheck 未找到腾讯云CLB配置");
            throw new BusinessException("未找到腾讯云CLB配置");
        }
        TencentCloudConfig config = configList.get(0);
        ClbClient client = TencentCloudClientUtil.createClbClient(config);
        //获取负载均衡列表
        LoadBalancer loadBalancer = getLoadBalancersByDomain(client, domain);
        String vip = loadBalancer.getLoadBalancerVips()[0];//负载均衡ip
        String loadBalancerId = loadBalancer.getLoadBalancerId();
        //获取负载均衡所需要的id
        TencentCloudCLBIdInfo clbIdInfo = getClbIdInfo(client, loadBalancerId, successSubDomain);
        String listenerId = clbIdInfo.getListenerId();
        if (StringUtils.isBlank(clbIdInfo.getListenerId())) {
            throw new BusinessException("CLB获取监听器失败,请前往配置");
        }
        //创建监听器规则
        String locationId = clbIdInfo.getLocationId();
        if (StringUtils.isBlank(clbIdInfo.getLocationId())) {
            locationId = createListenerRule(client, loadBalancerId, listenerId, successSubDomain);
        }
        //获取nginx 实例
        Instance[] instanceSet = getNginxInstance();
        List<String> instanceIds = Arrays.stream(instanceSet).map(instance -> instance.getInstanceId()).collect(Collectors.toList());
        List<String> bindInstanceIds = clbIdInfo.getInstanceIds();//已经绑定的实力id
        if (CollectionUtils.isNotEmpty(clbIdInfo.getInstanceIds())) {
            instanceIds.removeAll(bindInstanceIds);
        }
        //绑定实例列表
        if (CollectionUtils.isNotEmpty(instanceIds)) {
            listenerBindTargets(client, loadBalancerId, listenerId, locationId, instanceIds);
        }
        //2. 创建域名解析
        //创建域名解析(子域名)
        Long dnsRecord = createDnsRecord(configId, domainId, domain, subDomain, vip);
        TencentDnsRecord tencentDnsRecord = new TencentDnsRecord();
        tencentDnsRecord.setConfigId(configId);
        tencentDnsRecord.setRecordId(dnsRecord);
        tencentDnsRecord.setRecordName(subDomain);
        tencentDnsRecord.setValue(loadBalancer.getAddressIPv6());
        tencentDnsRecord.setDomainName(successSubDomain);
        tencentDnsRecord.setStatus("ENABLE");
        tencentDnsRecordService.insert(tencentDnsRecord);
        return QResult.success(successSubDomain);
    }

    @NotNull
    private String getSubDomain(DomainRecordRequest request) {
        String subDomain;
        //TODO 自动生成一个子域名
        String yyyyMMdd = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMddHH"));
        subDomain = request.getStartDomain() + yyyyMMdd;
        return subDomain;
    }


    /**
     * 添加域名解析记录
     *
     * @param configId
     * @param subDomain
     * @return
     */
    private Long createDnsRecord(String configId, long domainId, String domain, String subDomain, String locaBalancerVip) {
        log.info("addDnsRecord 添加域名解析记录 configId:{},domainId:{},subDomain:{},locaBalancerVip:{}", configId, domainId, subDomain, locaBalancerVip);

        //查询是否已经创建
        RecordListItem recordListItem = checkDnsRecord(configId, domain, subDomain);
        if (Objects.nonNull(recordListItem)) {
            return recordListItem.getRecordId();
        }

        TencentCloudConfig config = tencentCloudConfigService.findById(configId);
        if (Objects.isNull(config)) {
            throw new BusinessException("请先配置腾讯云的dns");
        }
        DnspodClient client = TencentCloudClientUtil.createDnsClient(config);
        CreateRecordRequest req = new CreateRecordRequest();
        req.setDomainId(domainId);
        req.setDomain(domain);
        req.setSubDomain(subDomain); // 如子域为"www"，则更新的是www.example.com的解析
        req.setRecordType("A");    // IPv6记录类型 默认A
        req.setRecordLine("默认");     // 线路类型
        req.setTTL(60l);
        req.setValue(locaBalancerVip);    // 新的IPv6地址 43.137.77.85
        req.setWeight(1L);
        //发送请求
        CreateRecordResponse createRecordResponse;
        try {
            createRecordResponse = client.CreateRecord(req);
        } catch (Exception e) {
            log.error("addDnsRecord error:{}", e.getMessage(), e);
            throw new BusinessException("DNS调用异常:添加解析记录");
        }
        // 从响应中获取记录ID，判断是否创建成功
        Long recordId = createRecordResponse.getRecordId();
        log.info("addDnsRecord 添加域名解析记录 recordId:{}", recordId);
        if (recordId == null || recordId <= 0) {
            throw new BusinessException("DNS调用异常:添加解析记录");
        }
        return recordId;
    }


    /**
     * 检查DNS解析记录是否重复
     */
    private RecordListItem checkDnsRecord(String configId, String domain, String subDomain) {
        TencentCloudConfig config = tencentCloudConfigService.findById(configId);
        if (Objects.isNull(config)) {
            throw new BusinessException("请先配置腾讯云的dns");
        }
        DnspodClient client = TencentCloudClientUtil.createDnsClient(config);
        //查询是否已经创建
        DescribeRecordListRequest dreq = new DescribeRecordListRequest();
        dreq.setDomain(domain);
        dreq.setKeyword(subDomain);
        try {
            // 发送请求
            DescribeRecordListResponse describeRecordList = client.DescribeRecordList(dreq);
            log.info("addDnsRecord 查询解析记录判断是否重复 describeRecordList:{}", JSON.toJSONString(describeRecordList));
            RecordListItem[] recordList = describeRecordList.getRecordList();
            if (ArrayUtils.isEmpty(recordList)) {
                return null;
            }
            for (RecordListItem recordListItem : recordList) {
                if (recordListItem.getName().equals(subDomain)) {
                    log.info("addDnsRecord 无需创建");
                    return recordListItem;
                }
            }
        } catch (TencentCloudSDKException e) {
            log.error("addDnsRecord code:{}error:{}", e.getErrorCode(), e.getMessage(), e);
            if (!"ResourceNotFound.NoDataOfRecord".equals(e.getErrorCode())) {
                throw new BusinessException("DNS调用异常:" + e.getMessage());
            }
        }
        return null;
    }

    /**
     * 根据域名获取负载均衡
     *
     * @param domain
     * @return
     */
    private LoadBalancer getLoadBalancersByDomain(ClbClient client, String domain) {
        log.info("getLoadBalancersByDomain 获取负载均衡 domain:{}", domain);
        //调用腾讯云 负载均衡接口
        DescribeLoadBalancersRequest req = new DescribeLoadBalancersRequest();
        if (StringUtils.isNotBlank(domain)) {
            req.setSearchKey(domain);
        }
        DescribeLoadBalancersResponse resp;
        try {
            resp = client.DescribeLoadBalancers(req);
        } catch (Exception e) {
            log.error("getLoadBalancersByDomain error:{}", e.getMessage(), e);
            throw new BusinessException("CLB调用异常:获取负载均衡");
        }
        if (ArrayUtils.isEmpty(resp.getLoadBalancerSet())) {
            log.error("getLoadBalancersByDomain LoadBalancerSet is null");
            throw new BusinessException("未找到负载均衡");
        }
        List<LoadBalancer> loadBalancers = Arrays.stream(resp.getLoadBalancerSet()).sorted((o1, o2) -> o2.getCreateTime().compareTo(o1.getCreateTime())).collect(Collectors.toList());
        //获取只获取第一个
        LoadBalancer loadBalancer = loadBalancers.get(0);
        log.info("getLoadBalancersByDomain 获取负载均衡 loadBalancer:{}", JSONObject.toJSONString(loadBalancer));
        return loadBalancer;
    }

    /**
     * 获取负载均衡clb 所需要的id
     *
     * @param loadBalancerId
     * @param domain
     * @return
     */
    private TencentCloudCLBIdInfo getClbIdInfo(ClbClient client, String loadBalancerId, String domain) {
        //查询是否已经绑定  避免重复绑定
        TencentCloudCLBIdInfo idInfo = new TencentCloudCLBIdInfo();
        try {
            DescribeTargetsRequest dreq = new DescribeTargetsRequest();
            dreq.setLoadBalancerId(loadBalancerId);
            dreq.setPort(443L);
            // 调用接口
            DescribeTargetsResponse resp = client.DescribeTargets(dreq);
            ListenerBackend[] listeners = resp.getListeners();
            log.info("getTencentCloudRepeatCheck 验证是否重复  listeners:{}", JSONObject.toJSONString(listeners));
            if (ArrayUtils.isEmpty(listeners)) {
                return idInfo;
            }
            //获取监听器id
            ListenerBackend listener = listeners[0];
            idInfo.setListenerId(listener.getListenerId());

            RuleTargets[] rules = listener.getRules();
            if (ArrayUtils.isEmpty(rules)) {
                return idInfo;
            }
            List<RuleTargets> domainRuleTargets = Arrays.stream(rules).filter(rule -> rule.getDomain().equals(domain) && rule.getUrl().equals("/")).collect(Collectors.toList());
            if (CollectionUtils.isEmpty(domainRuleTargets)) {
                return idInfo;
            }
            //获取规则id
            RuleTargets ruleTargets = domainRuleTargets.get(0);
            String locationId = ruleTargets.getLocationId();
            idInfo.setLocationId(locationId);
            //绑定实例目标
            Backend[] targets = ruleTargets.getTargets();
            if (ArrayUtils.isEmpty(targets)) {
                return idInfo;
            }
            //获取绑定实例id
            List<String> instanceIds = Arrays.stream(targets).map(Backend::getInstanceId).collect(Collectors.toList());
            idInfo.setInstanceIds(instanceIds);
        } catch (Exception e) {
            throw new BusinessException("查询绑定实例异常,请手动前往绑定");
        }
        return idInfo;
    }

    /**
     * 创建监听器 规则
     *
     * @param loadBalancerId 负载均衡id
     * @param listenerId     监听器id
     * @param domain         规则域名
     * @return
     */
    private String createListenerRule(ClbClient client, String loadBalancerId, String listenerId, String domain) {
        log.info("createListenerRule 创建监听器规则参数 loadBalancerId:{},listenerId:{},domain:{}, ", loadBalancerId, listenerId, domain);
        //创建监听器规则
        CreateRuleRequest req = new CreateRuleRequest();
        req.setLoadBalancerId(loadBalancerId); // CLB实例ID
        req.setListenerId(listenerId);         // 监听器ID

        // 配置转发规则（支持多规则）
        RuleInput rule = new RuleInput();
        rule.setDomain(domain);     // 匹配域名
        rule.setUrl("/");                  // 匹配URL路径（支持通配符）
        rule.setSessionExpireTime(60L);      // 会话保持时间（秒）
        rule.setScheduler("WRR");              // 均衡方式：WRR/LEAST_CONN/IP_HASH
        rule.setForwardType("HTTPS");
        //健康检查
        HealthCheck healthCheck = new HealthCheck();
        healthCheck.setHealthSwitch(1L); // 0表示关闭，1表示开启
        healthCheck.setHttpCheckPath("/");
        rule.setHealthCheck(healthCheck); // 关联到RuleInput

        RuleInput[] ruleInputs = {rule};
        req.setRules(ruleInputs);
        CreateRuleResponse resp;
        try {
            resp = client.CreateRule(req);
        } catch (Exception e) {
            log.error("createListenerRule error:{}", e.getMessage(), e);
            throw new BusinessException("CLB调用异常:创建监听器规则");
        }
        // 调用接口
        if (ArrayUtils.isEmpty(resp.getLocationIds())) {
            log.error("createListenerRule listeners is null");
            throw new BusinessException("负载均衡未找到监听器");
        }
        String locationId = resp.getLocationIds()[0];
        log.info("createListenerRule 创建监听器规则结果 locationId:{}, ", locationId);
        return locationId;
    }

    /**
     * 获取nginx 实例
     *
     * @return
     */
    private Instance[] getNginxInstance() {
        log.info("getNginxInstance 获取nginx实例");
        // 目前 instance 只有一个配置
        List<TencentCloudConfig> configList = tencentCloudConfigService.findByType(TencentCloudConfig.INSTANCE);
        if (Collections.isEmpty(configList)) {
            log.error("getNginxInstance 未找到腾讯云INSTANCE配置");
            throw new BusinessException("未找到腾讯云INSTANCE配置");
        }
        TencentCloudConfig config = configList.get(0);
        //调用腾讯云 获取实例接口
        DescribeInstancesRequest req = new DescribeInstancesRequest();
        Filter filter = new Filter();
        filter.setName("instance-name"); // 固定字段名，表示按名称过滤
        filter.setValues(new String[]{"Nginx-Slaves", "Nginx-Master"}); // 关键词（如图中的"nginx"）
        req.setFilters(new Filter[]{filter});

        CvmClient cvmClient = TencentCloudClientUtil.createInstanceClient(config);
        DescribeInstancesResponse resp;
        try {
            resp = cvmClient.DescribeInstances(req);
        } catch (TencentCloudSDKException e) {
            log.error("getNginxInstance error:{}", e.getMessage(), e);
            throw new BusinessException("INSTANCE调用异常:获取Nginx实例失败");
        }
        // 调用接口
        if (ArrayUtils.isEmpty(resp.getInstanceSet())) {
            log.error("getNginxInstance instanceSet is null");
            throw new BusinessException("获取Nginx实例失败");
        }
        Instance[] instanceSet = resp.getInstanceSet();
        log.info("getNginxInstance 获取nginx实例结果 instanceSet:{}", JSONObject.toJSONString(instanceSet));
        return instanceSet;
    }


    /**
     * 监听器绑定后端实例
     *
     * @param loadBalancerId
     * @param listenerId
     * @param locationId
     * @param instanceIds
     * @return
     */
    public void listenerBindTargets(ClbClient client, String loadBalancerId, String listenerId, String locationId, List<String> instanceIds) {
        log.info("listenerBindTargets 监听器绑定实例参数 loadBalancerId:{},listenerId:{},locationId:{},instanceIds:{}", loadBalancerId, listenerId, locationId, instanceIds);
        // 调用腾讯云 监听器绑定后端实例接口
        RegisterTargetsRequest req = new RegisterTargetsRequest();
        req.setLoadBalancerId(loadBalancerId);//负载均衡id
        req.setListenerId(listenerId);//监听器id
        req.setLocationId(locationId); // 规则ID（从CreateRule返回）
        //绑定目标实例封装
        Target[] targets = new Target[instanceIds.size()];
        for (int i = 0; i < instanceIds.size(); i++) {
            Target target = new Target();
            target.setInstanceId(instanceIds.get(i)); // CVM实例ID
            target.setPort(443L);            // 绑定实例端口
            target.setWeight(1L);            // 权重（0-100）
            targets[i] = target;
        }
        req.setTargets(targets);//绑定目标
        //获取客户端
        RegisterTargetsResponse resp;
        try {  // 调用接口
            resp = client.RegisterTargets(req);
        } catch (Exception e) {
            log.error("listenerBindTargets 监听器绑定实例异常5秒后重试 error:{}", e.getMessage(), e);
            try {
                Thread.sleep(20000);
            } catch (InterruptedException te) {
                log.info("listenerBindTargets error:{}", e);
            }
            //补偿执行
            try {
                resp = client.RegisterTargets(req);
            } catch (Exception e2) {
                log.error("listenerBindTargets 监听器绑定实例重试异常  error:{}", e2.getMessage(), e2);
                throw new BusinessException("绑定实例异常,请手动前往绑定");
            }
        }
        String requestId = resp.getRequestId();
        log.info("listenerBindTargets 监听器绑定实例结果 requestId:{}", requestId);
        if (StringUtils.isBlank(requestId)) {
            throw new BusinessException("绑定实例异常,请手动前往绑定");
        }
    }


    /**
     * 获取负载均衡
     *
     * @return
     */
    private LoadBalancer[] getLoadBalancers() {
        log.info("getLoadBalancers 获取负载均衡");
        // 目前 clb 只有一个配置
        List<TencentCloudConfig> configList = tencentCloudConfigService.findByType(TencentCloudConfig.CLB);
        if (Collections.isEmpty(configList)) {
            log.error("getLoadBalancers 未找到腾讯云CLB配置");
            throw new BusinessException("未找到腾讯云CLB配置");
        }
        TencentCloudConfig config = configList.get(0);
        //调用腾讯云 负载均衡接口
        DescribeLoadBalancersRequest req = new DescribeLoadBalancersRequest();
        ClbClient client = TencentCloudClientUtil.createClbClient(config);
        DescribeLoadBalancersResponse resp;
        try {
            resp = client.DescribeLoadBalancers(req);
        } catch (Exception e) {
            log.error("getLoadBalancers error:{}", e.getMessage(), e);
            throw new BusinessException("CLB调用异常:获取负载均衡");
        }
        if (ArrayUtils.isEmpty(resp.getLoadBalancerSet())) {
            log.error("getLoadBalancers LoadBalancerSet is null");
            throw new BusinessException("未找到负载均衡");
        }
        LoadBalancer[] loadBalancerSet = resp.getLoadBalancerSet();
        log.info("getLoadBalancers 获取负载均衡 loadBalancer:{}", JSONObject.toJSONString(loadBalancerSet));
        return loadBalancerSet;
    }

}
